import scala.collection.mutable.ListBuffer

object ClassAndObjectDemo extends App {
  // 1. 定义学生类
  class Student(
                 val studentId: String, // val 定义只读属性
                 var name: String, // var 定义可读写属性
                 private var _gender: String, // 私有属性，通过方法访问
                 var age: Int,
                 var major: String
               ) {
    // 主构造器执行代码
    require(studentId.nonEmpty, "学号不能为空")
    require(name.nonEmpty, "姓名不能为空")
    require(_gender == "男" || _gender == "女", "性别必须是'男'或'女'")
    require(age > 0 && age < 120, "年龄必须在合理范围内")

    // 辅助构造器
    def this(studentId: String, name: String, gender: String) {
      this(studentId, name, gender, 18, "未确定") // 调用主构造器
    }

    // 定义方法：获取性别（封装私有属性）
    def gender: String = _gender

    // 定义方法：修改性别（带验证）
    def setGender(newGender: String): Unit = {
      if (newGender == "男" || newGender == "女") {
        _gender = newGender
      } else {
        println("性别必须是'男'或'女'")
      }
    }

    // 定义方法：显示学生信息
    def showInfo(): Unit = {
      println(s"学号: $studentId")
      println(s"姓名: $name")
      println(s"性别: $_gender")
      println(s"年龄: $age")
      println(s"专业: $major")
    }

    // 重写toString方法
    override def toString: String =
      s"Student($studentId, $name, $_gender, $age, $major)"
  }

  // 2. 创建对象（类的实例）
  val student1 = new Student("S2025001", "张三", "男", 20, "计算机科学")
  val student2 = new Student("S2025002", "李四", "女") // 使用辅助构造器

  // 3. 访问对象属性和方法
  println("==学生1信息===")
  student1.showInfo()
  println("\n===学生2信息(初始)===")
  println(student2) // 调用toString方法
  // 修改属性
  student2.age = 19
  student2.major = "软件工程"
  student2.setGender("女") // 有效修改
  student2.setGender("保密") // 无效修改
  println("\n===学生2信息(修改后)===")
  student2.showInfo()

  // 4. 类的组合：定义班级类，包含学生
  class Class(
               val classId: String,
               val className: String,
               private val students: ListBuffer[Student] = ListBuffer.empty
             ) {
    // 添加学生
    def addStudent(student: Student): Unit = {
      if (!students.exists(_.studentId == student.studentId)) {
        students += student
        println(s"学生 ${student.name} 已加入 $className")
      } else {
        println(s"学生 ${student.studentId} 已在班级中")
      }
    }

    // 查找学生
    def findStudent(studentId: String): Option[Student] = {
      students.find(_.studentId == studentId)
    }

    // 获取班级人数
    def studentCount: Int = students.size

    // 显示班级所有学生
    def showAllStudents(): Unit = {
      println(s"\n=== $className 学生列表 (共 ${studentCount} 人)===")
      students.foreach(println)
    }
  }

  // 5. 使用班级类
  val csClass = new Class("CS2025", "计算机2025级")
  csClass.addStudent(student1)
  csClass.addStudent(student2)
  csClass.addStudent(student1) // 重复添加
  csClass.showAllStudents()

  // 查找学生
  val found = csClass.findStudent("S2025001")
  found match {
    case Some(student) => println(s"\n找到学生: ${student.name}")
    case None => println("\n未找到该学生")
  }

  // 教师类
  class Teacher(
                 val teacherId: String,
                 var name: String,
                 var title: String // 职称
               ) {
    // 教授的课程
    private val courses = scala.collection.mutable.Set.empty[String]

    // 添加课程
    def addCourse(courseId: String): Unit = {
      courses += courseId
    }

    // 移除课程
    def removeCourse(courseId: String): Unit = {
      courses -= courseId
    }

    // 获取所有课程
    def getCourses: Set[String] = courses.toSet

    override def toString: String =
      s"Teacher($teacherId, $name, $title, 课程: ${courses.mkString(",")})"
  }

  // 使用教师类
  val teacher1 = new Teacher("T1001", "王教授", "教授")
  teacher1.addCourse("C101")
  teacher1.addCourse("C102")
  println("\n=== 教师信息 ===")
  println(teacher1)
}
